﻿
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Protocol.SouthGridProtocol.Blocks;
using Protocol.SouthGridProtocol.Decoder;
using Protocol.SouthGridProtocol.Encoder;
using PacoToolKit.Format;
namespace Protocol.SouthGridProtocol.Model
{
    public class C0AH
    {
        private static Seq seq = new Seq(0, 1, 1, 1, 2);
        private static C c = new C(0, 1, 1, null, 0, 11);//prm=1,funcode=11
        private static string afn = "0A";
        private static string head = "68";
        private static string bottom = "16";


        /// <summary>
        /// di数据长度表(字节)，若不能在改表找到的di，则表示该di是需要单独在匹配长度的，比如不定长，或者需要根绝设置来选择di
        /// </summary>
        private static Hashtable lenHashTable = new Hashtable {
            //通信参数
            {"E0000100",9},{"E0000101",9},{"E0000102",9},{"E0000103",8},{"E0000104",16},{"E0000105",32},{"E0000106",32},
            {"E0000107",1},{"E0000108",1},{"E0000109",1},{"E000010A",1},{"E000010B",1},{"E0000120",3},{"E0000121",3},{"E0000122",1},
            {"E0000123",2},{"E0000124",4},{"E0000125",4},{"E0000126",4},{"E0000127",1},
            //时间参数
            {"E0000130",6},{"E0000131",4},
            //复位操作(只写这里不用)
            {"E0000140",1},
            //告警屏蔽
            {"E0000150",32},{"E0000151",32},{"E0000152",32},{"E0000153",32},
            //结算日参数
            {"E0000160",2},{"E0000161",2},{"E0000162",2},{"E0000163",1},
            //身份认证
            {"E0000170",1},{"E0000171",16},{"E0000172",16},{"E0000173",16},{"E0000174",16},
            //阈值参数
            {"E0000180",1},{"E0000181",1},{"E0000182",1},{"E0000183",1},{"E0000184",1},{"E0000185",1},{"E0000186",1},
            {"E0000187",1},{"E0000188",1},{"E0000189",1},{"E000018A",2},{"E000018B",3},{"E000018C",3},
            //抄表参数
            {"E0000200",7},{"E0000201",7},{"E0000202",7},{"E0000203",7},{"E0000204",7},
            {"E0000205",7},{"E0000206",7},{"E0000207",7},{"E0000208",7},{"E0000209",7},
            {"E0000210",7},{"E0000211",7},{"E0000212",7},{"E0000213",7},{"E0000214",7},
            {"E0000215",7},{"E0000216",7},{"E0000217",7},{"E0000218",7},{"E0000219",7},{"E0000220",7},
            {"E0000221",1},//{"E0000222",1} 不定长
            //任务参数 
            {"E0000300",1},{"E0000400",1},
            //运算量参数
            {"E0000500",1},{"E00005FE",32},{"E0000600",1},{"E00006FE",32},{"E0000700",1},{"E00007FE",32},{"E0000800",1},{"E00008FE",32},{"E0000900",1},
            //端口参数
            //级联参数
            {"E0000A20",24},{"E0000A21",4},{"E0000A22",4},{"E0000A23",1},{"E0000A24",1},{"E0000A25",2},{"E0000A26",2},
            {"E0000A30",1},{"E0000A31",4},{"E0000A32",4},{"E0000A33",8},
            //版本参数
            {"E0000B00",2},{"E0000B01",6},{"E0000B02",2},
            //负荷管理参数
            //测量点控制参数(只写这里不用)
            //用户自定义数据（不定长）
            //测量点参数
            {"E0800000",1},{"E0800001",1},{"E0800002",6},{"E0800003",1},{"E0800004",1},{"E0800005",1},
            {"E0800006",1},{"E0800007",1},{"E0800008",1},{"E0800009",6},{"E080000A",1},{"E080000B",4},
            {"E080000C",2},{"E080000D",2},{"E0800010",1},{"E0800011",2},{"E0800012",3},{"E0800013",2},
            {"E0800014",2},{"E0800021",8},{"E0800022",8},
            //终端特有参数
            {"E1800001",2},{"E1800002",1},{"E1800003",1},{"E1800004",2},{"E1800005",2},
            {"E1800006",2},{"E1800007",2},{"E1800008",2},{"E1800009",16},{"E1800010",3},
            {"E1800011",2},{"E1800012",2},{"E1800013",3},{"E1800014",3},{"E1800015",1},
            {"E1800016",2},{"E1800017",2},{"E1800018",9},{"E1800019",2}
        };

        /// <summary>
        /// 组成下发查询的报文
        /// </summary>
        /// <param name="concentrator">集中器地址或者地址域，不小于6字节</param>
        /// <param name="dataList"></param>
        /// <returns></returns>
        public static string EncodeC0AH(string concentrator, List<CData> dataList)
        {
            //主站启动的发送帧的MSA应为非零值,终端启动发送帧的MSA应为零，其主站响应帧的MSA也应为零
            concentrator = concentrator.Substring(0, 12) + "01";

            StringBuilder sb = new StringBuilder();
            foreach (CData data in dataList)
            {
                sb.Append(data.da); sb.Append(data.di);
            }
            StringBuilder msgsb = new StringBuilder();
            string length = BaseEncoder.CalcLength(c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString());
            string cs = BaseEncoder.CalcCSCode(c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString());
            return head + length + length + head + c.encodeC() + concentrator + afn + seq.encodeSeqString() + sb.ToString() + cs + bottom;
        }

        /// <summary>
        /// 根据报文解析C0AH的数据块内容到数据块列表
        /// </summary>
        /// <param name="msg"></param>
        /// <returns></returns>
        public static List<CData> DecodeC0AH(string msg)
        {
            List<CData> dataList = new List<CData>();

            int msgLength = BaseDecoder.GetLength(msg);//字节数


            int dataRemainLen = (msgLength - 10) * 2;//初始 剩余未读数据长度
            string dataRemain = msg.Substring(32, dataRemainLen);//初始 剩余未读数据

            //循环读取块
            while (dataRemainLen >= 12)
            {
                string da = dataRemain.Substring(0, 4);
                string di = dataRemain.Substring(4, 8);
                int currentDataBlockLength = 0;
                string data = string.Empty;
                if (Formater.ReverseHexString(di).Equals("E0000222"))
                {
                    //抄表参数配置
                    data = dataRemain.Substring(12, 8 * 2);
                    int groupCount = int.Parse(Formater.HEXtoDEC(dataRemain.Substring(28, 2)));
                    data += dataRemain.Substring(30, groupCount * 4 * 2);
                }
                else if (Formater.ReverseHexString(di).Substring(0,6).Equals("E0000A")&&int.Parse(Formater.HEXtoDEC(di.Substring(0,2)))<=30)
                {
                    //端口参数
                    currentDataBlockLength = 5;
                    data = dataRemain.Substring(12, currentDataBlockLength * 2);
                }
                else
                {
                    currentDataBlockLength = (int)lenHashTable[Formater.ReverseHexString(di)];
                    data = dataRemain.Substring(12, currentDataBlockLength * 2);
                }


                dataList.Add(new CData { da = da, di = di, data = data });//读完一块，加入列表

                //重新计算剩余未读数据
                dataRemain = dataRemain.Remove(0, (4 + 8 + currentDataBlockLength * 2));
                dataRemainLen = dataRemain.Length;
            }

            return dataList;
        }
    }
}
